/**
 * Copyright (C) 2012 GreenSoft S.A.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ar.com.greensoft.neosystem.dao.jpa;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;

import ar.com.greensoft.neosystem.dao.LocalidadDao;
import ar.com.greensoft.neosystem.model.address.Localidad;
import ar.com.greensoft.neosystem.model.address.Localidad_;
import ar.com.greensoft.neosystem.model.address.Provincia;
import ar.com.greensoft.neosystem.search.SearchFilter;
import ar.com.greensoft.neosystem.search.address.LocalidadSearchFilter;
import ar.com.greensoft.neosystem.util.SearchUtil;

/**
 * Java Persistence API Implementation of Localidad Data Access Object Pattern
 * @author Jorge E. Villaverde
 * @version 1.0.0
 * @since 1.0.0
 */
@Stateless
public class JpaLocalidadDaoImpl extends AbstractLongIdJpaDaoImpl<Localidad> implements LocalidadDao{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	protected Class<Localidad> getEntityClazz() {
		return Localidad.class;
	}

	@Override
	protected String getFindByNameNamedQuery() {
		return Localidad.FIND_BY_NAME_QUERY_NAME;
	}
	
	@Override
	public List<Localidad> findLikeName(String name) {
		logger.trace("Returning the list of " + getEntityClazz().getSimpleName() + " with name like: " + name);
		
		TypedQuery<Localidad> query = 
				getEntityManager().createNamedQuery(Localidad.FIND_LIKE_NAME_QUERY_NAME, Localidad.class);

		query.setParameter("name", name);

		return query.getResultList();
	}

	@Override
	protected Expression<Boolean> createWhereFromSearchFilter(SearchFilter searchFilter, Root<Localidad> root) {
		if(searchFilter == null || !searchFilter.hasFilter())
			return null;
		LocalidadSearchFilter lsf = (LocalidadSearchFilter)searchFilter;
		Predicate predicate = null;
		
		CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
		
		if(lsf.getProvincia() != null){
			Predicate provinciaPedicate = builder.equal(
					root.get(Localidad_.provincia), 
					lsf.getProvincia());
			predicate = appendAndPredicate(predicate, provinciaPedicate);
		}
		if(!StringUtils.isBlank(lsf.getNombre())){
			String searchText = SearchUtil.likeString(lsf.getNombre());
			Predicate nombrePedicate = builder.like(
					root.get(Localidad_.name), 
					searchText);
			predicate = appendAndPredicate(predicate, nombrePedicate);
		}
			
		return predicate;		
	}
	
	protected List<Order> createOrders(Root<Localidad> root){
		List<Order> ret = new ArrayList<Order>();
		CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
		ret.add(builder.asc(root.get(Localidad_.name)));
		return ret;
	}


	@Override
	public List<Localidad> findByProvincia(Provincia provincia) {
		if(provincia == null)
			throw new IllegalArgumentException("Provincia is null");
		
		logger.trace("Returning the list of " + getEntityClazz().getSimpleName() + " with Provincia = " + provincia.getName());
		
		TypedQuery<Localidad> query = 
				getEntityManager().createNamedQuery(Localidad.FIND_BY_PROVINCIA_QUERY_NAME, Localidad.class);

		query.setParameter("provincia", provincia);

		return query.getResultList();
	}

	@Override
	public Localidad findByProvinciaName(Provincia provincia, String name) {
		if(provincia == null)
			throw new IllegalArgumentException("Provincia is null");
		
		logger.trace("Returning the list of " + getEntityClazz().getSimpleName() + " with Provincia = " + provincia.getName());
		
		TypedQuery<Localidad> query = 
				getEntityManager().createNamedQuery(Localidad.FIND_BY_PROVINCIA_NAME_QUERY_NAME, 
				Localidad.class);

		query.setParameter("provincia", provincia);
		query.setParameter("name", name);

		return findSingleResult(query);
	}
}